package com.springBoot.springBootSysCore.modules.entity.system;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.persistence.*;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import com.alibaba.fastjson.annotation.JSONField;
import com.google.gson.annotations.Expose;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.*;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.springBoot.springBootSysCore.common.StaticConfig;
import com.springBoot.springBootSysCore.common.comment.annotation.ManyToManyComment;
import com.springBoot.springBootSysCore.common.comment.annotation.MyComment;
import com.springBoot.springBootSysCore.common.persistence.DataEntity;
import com.springBoot.springBootSysCore.common.utils.encoding.Encodes;

/**
 * 用户
 *
 *
 * 1、@JsonIgnoreProperties
 此注解是类注解，作用是json序列化时将java bean中的一些属性忽略掉，序列化和反序列化都受影响。
 写法将此标签加在model 类的类名上 ，可以多个属性也可以单个属性
 2、@JsonIgnore
 此注解用于属性或者方法上（最好是属性上），作用和上面的@JsonIgnoreProperties一样。
 3、@JsonFormat
 此注解用于属性或者方法上（最好是属性上），可以方便的把Date类型直接转化为我们想要的模式，比如@JsonFormat(pattern = “yyyy-MM-dd HH-mm-ss”)
 4、@JsonSerialize
 此注解用于属性或者getter方法上，用于在序列化时嵌入我们自定义的代码，比如序列化一个double时在其后面限制两位小数点。
 5、@JsonDeserialize
 此注解用于属性或者setter方法上，用于在反序列化时可以嵌入我们自定义的代码，类似于上面的@JsonSerialize
 6、@Transient
 //	@JsonIgnore注解用来忽略某些字段，可以用在Field或者Getter方法上，用在Setter方法时，和Filed效果一样。这个注解只能用在POJO存在的字段要忽略的情况。
 //	@JsonIgnoreProperties(ignoreUnknown = true)，将这个注解写在类上之后，就会忽略类中不存在的字段，可以满足当前的需要。这个注解还可以指定要忽略的字段。使用方法如下：
 //	@JsonIgnoreProperties({ "internalId", "secretKey" })
 //	指定的字段不会被序列化和反序列化。
 //	到此顺利解决。（还有Gson有类似的实现请告知一下，本人只知道gson转string忽略字段的方法，谢谢）
 //	参考：
 //	http://blog.csdn.net/isea533/article/details/33397735
 //	http://www.cnblogs.com/dupang/p/5673097.html

 @OneToMany(mappedBy="item",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
 @Fetch(value=FetchMode.SUBSELECT)
 两者比较：
 两者都是设定关联对象的加载策略。前者是JPA标准的通用加载策略注解属性，
 后者是Hibernate自有加载策略注解属性。
 FetchType可选值意义与区别如下：
 FetchType.LAZY: 懒加载，在访问关联对象的时候加载(即从数据库读入内存)
 FetchType.EAGER:立刻加载，在查询主对象的时候同时加载关联对象。
 FetchMode可选值意义与区别如下：
 @Fetch(FetchMode.JOIN)： 始终立刻加载，使用外连(outer join)查询的同时加载关联对象，忽略FetchType.LAZY设定。
 @Fetch(FetchMode.SELECT) ：默认懒加载(除非设定关联属性lazy=false)，当访问每一个关联对象时加载该对象，会累计产生N+1条sql语句
 @Fetch(FetchMode.SUBSELECT)  默认懒加载(除非设定关联属性lazy=false),在访问第一个关联对象时加载所有的关联对象。会累计产生两条sql语句。且FetchType设定有效。

 * @author timo ,uniqueConstraints=@UniqueConstraint(columnNames="ACCOUNT") 唯一约束
 * , uniqueConstraints = @UniqueConstraint(columnNames = { "account", "email" })
 */
@Entity
@Table(name = "SYS_USER")
@MyComment("用户表")
@Component("sysUser")
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler","createBy"})
public class SysUser extends DataEntity<SysUser> {
	private String account;// 账号
	private String password;// 密码
	private String available = "false";// 是否锁定
	private String activation = "true";// 是否激活
	private String userType;// 用户类型

	private Date birthday;//生日
	private Integer age;// 年龄
	private String realName;// 真实姓名
	@Expose
	private String nickName;// 昵称
	private Integer sex;// 性别 0-女 1 男
	@Expose
	private String photo;// 照片头像
	private String phone;// 电话
	private String showPhone;// 解密后的邮箱--没有数据库关联
	private String email;// 电子邮件
	private String showEmail;// 解密后的邮箱--没有数据库关联
	private String address;//所属城市

	private String loginIp; // 最后登陆IP
	private Date loginDate; // 最后登陆日期
	private String oldLoginIp; // 上次登陆IP
	private Date oldLoginDate; // 上次登陆日期

	private String clientDigest;//无状态登录加密值
	private SysRole defalutRole;// 基础角色-ManyToOne
	private List<SysRole> roleList;// 角色
	private List<SysOrganization> orgList;// 部门
	private List<SysMessage> receiveMessage;// 用户接收消息
	private List<SysMessageLog> sysMessageLogs;//用户接受的公告消息的阅读记录

	private String oldLoginName;// 原登录名
	private String newPassword; // 新密码
	/**********************************/


	public SysUser() {
	}

	public SysUser(String id, String account) {
		super(id);
		this.account = account;
	}
	@Column(name = "CLIENT_DIGEST")
	@MyComment("无状态登录")
	public String getClientDigest() {
		return clientDigest;
	}

	public void setClientDigest(String clientDigest) {
		this.clientDigest = clientDigest;
	}

	@Column(name = "ACCOUNT")
	@MyComment("登陆账号")
	@NotNull(message = "账号不能为空")
	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	@Column(name = "PASSWORD")
	@MyComment("登陆密码")
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(name = "IS_ENABLED")
	@MyComment("是否锁定")
	public String getAvailable() {
		return available;
	}

	public void setAvailable(String available) {
		this.available = available;
	}

	@Column(name = "NICK_NAME")
	@MyComment("昵称")
	public String getNickName() {
		return nickName;
	}

	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	@Column(name = "SEX")
	@MyComment("性别  1:男  0:女")
	public Integer getSex() {
		return sex;
	}

	public void setSex(Integer sex) {
		this.sex = sex;
	}

	@Column(name = "BIRTHDAY")
	@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+08:00")
	@DateTimeFormat(pattern = "yyyy-MM-dd")
	/* @Temporal(TemporalType.TIMESTAMP) */
	@MyComment("生日")
	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	@Column(name = "PHOTO")
	@MyComment("照片")
	public String getPhoto() {
		return photo;
	}

	public void setPhoto(String photo) {
		this.photo = photo;
	}
	@Column(name = "ADDRESS")
	@MyComment("地址")
	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Column(name = "email")
	@MyComment("注册邮箱")
	public String getEmail() {
		return email == null ? "" : email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Transient
	public String getShowEmail() {
		String val = getEmail();
//		if (StringUtils.isNotBlank(val)) {
//			showEmail = Encodes.decrypt(val, StaticConfig.DES_PASSWORD);
//		}
		return val;
	}

	public void setShowEmail(String showEmail) {
		this.showEmail = showEmail;
	}

	@Column(name = "phone")
	@MyComment("注册邮箱")
	public String getPhone() {
		return phone == null ? "" : phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	@Transient
	public String getShowPhone() {
//		String val = getPhone();
//		if (StringUtils.isNotBlank(val)) {
//			showPhone = Encodes.decrypt(val, StaticConfig.DES_PASSWORD);
//		}
		return getPhone();
	}

	public void setShowPhone(String showPhone) {
		this.showPhone = showPhone;
	}

	@Column(name = "IS_ACTIVATION")
	@MyComment("是否激活")
	public String getActivation() {
		return activation;
	}

	public void setActivation(String activation) {
		this.activation = activation;
	}

	@Column(name = "AGE")
	@MyComment("年龄")
	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Column(name = "REALNAME")
	@MyComment("真实姓名")
	public String getRealName() {
		return realName;
	}

	public void setRealName(String realName) {
		this.realName = realName;
	}

//	cascade={CascadeType.MERGE,CascadeType.PERSIST},
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "DEFALUT_ROLE")
	@MyComment("基础角色")
	@JsonIgnore
	@LazyToOne(LazyToOneOption.PROXY)
	public SysRole getDefalutRole() {
		return defalutRole;
	}

	public void setDefalutRole(SysRole defalutRole) {
		this.defalutRole = defalutRole;
	}

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "SYS_USER_ROLE", joinColumns = @JoinColumn(name = "USER_ID") , inverseJoinColumns = @JoinColumn(name = "ROLE_ID") )
	@JsonIgnore
	@ManyToManyComment(tableComment = "用户与角色关系表", joinColumn = "用户ID", inverseJoinColumn = "角色ID")
	@LazyCollection(LazyCollectionOption.TRUE)
	public List<SysRole> getRoleList() {
		return roleList;
	}

	public void setRoleList(List<SysRole> roleList) {
		this.roleList = roleList;
	}

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "SYS_USER_ORG", joinColumns = @JoinColumn(name = "USER_ID") , inverseJoinColumns = @JoinColumn(name = "ORG_ID") )
	@JsonIgnore
	@ManyToManyComment(tableComment = "用户与机构关系表", joinColumn = "用户ID", inverseJoinColumn = "机构ID")
	@LazyCollection(LazyCollectionOption.TRUE)
	public List<SysOrganization> getOrgList() {
		return orgList;
	}

	public void setOrgList(List<SysOrganization> orgList) {
		this.orgList = orgList;
	}

	@OneToMany(mappedBy = "toSysUser", cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
	@JsonIgnore
	public List<SysMessage> getReceiveMessage() {
		return receiveMessage;
	}

	public void setReceiveMessage(List<SysMessage> receiveMessage) {
		this.receiveMessage = receiveMessage;
	}

	@OneToMany(mappedBy = "sysUser", cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
	@JsonIgnore
	public List<SysMessageLog> getSysMessageLogs() {
		return sysMessageLogs;
	}

	public void setSysMessageLogs(List<SysMessageLog> sysMessageLogs) {
		this.sysMessageLogs = sysMessageLogs;
	}

	@Column(name = "LOGIN_IP")
	@MyComment("最后登录ip")
	public String getLoginIp() {
		return loginIp;
	}

	public void setLoginIp(String loginIp) {
		this.loginIp = loginIp;
	}
	@Column(name = "LOGIN_DATE")
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	/* @Temporal(TemporalType.TIMESTAMP) */
	@MyComment("最后登录时间")
	public Date getLoginDate() {
		return loginDate;
	}

	
	public void setLoginDate(Date loginDate) {
		this.loginDate = loginDate;
	}
	@Column(name = "OLD_LOGIN_IP")
	@MyComment("上次登录ip")
	public String getOldLoginIp() {
		return oldLoginIp;
	}

	public void setOldLoginIp(String oldLoginIp) {
		this.oldLoginIp = oldLoginIp;
	}
	@Column(name = "OLD_LOGIN_DATE")
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	/* @Temporal(TemporalType.TIMESTAMP) */
	@MyComment("上次登录时间")
	public Date getOldLoginDate() {
		return oldLoginDate;
	}

	public void setOldLoginDate(Date oldLoginDate) {
		this.oldLoginDate = oldLoginDate;
	}
	@Column(name = "USER_TYPE")
	@MyComment("用户类型")
	public String getUserType() {
		return userType;
	}

	public void setUserType(String userType) {
		this.userType = userType;
	}

	@Transient
	public String getOldLoginName() {
		return oldLoginName;
	}
	public void setOldLoginName(String oldLoginName) {
		this.oldLoginName = oldLoginName;
	}
	@Transient
	public String getNewPassword() {
		return newPassword;
	}
	public void setNewPassword(String newPassword) {
		this.newPassword = newPassword;
	}
	@Transient
	public boolean isAdmin(){
		return isAdmin(this.id);
	}
	@Transient
	public static boolean isAdmin(String id){
		return id != null && "1".equals(id);
	}

}
